#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;

class Solution01 {
public:
    int pivotIndex(vector<int>& nums) {
        int len = nums.size();
        vector<int> dp(len + 1);
        dp[0] = 0;
        int sum = 0;
        for (int i = 1; i <= len; i++) {
            dp[i] =dp[i - 1] + nums[i - 1];
            sum += nums[i - 1];
        }
        for (int i = 1; i <= len; i++) {
            if (dp[i - 1] == sum - dp[i])
                return i - 1;
        }

        return -1;
    }
};

class Solution02 {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int len = nums.size();
        vector<int> f(len + 1), g(len + 1), ans;
        f[0] = g[len - 1] = 1;
        for (int i = 1; i < len; i++)
            f[i] = f[i - 1] * nums[i - 1];
        for (int i = len - 2; i >= 0; i--)
            g[i] = g[i + 1] * nums[i + 1];
        for (int i = 0; i < len; i++) 
            ans.emplace_back(f[i] * g[i]);
        return ans;
    }
};

class Solution03 {
public:
    int subarraySum(vector<int>& nums, int k) {
        int cnt = 0;
        unordered_map<int, int> hash;
        hash[0] = 1;
        int sum = 0;
        for (auto e : nums) {
            sum += e;
            if (hash.count(sum - k)) cnt += hash[sum - k];
            hash[sum]++;
        }
        return cnt;
    }
};

class Solution04 {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        unordered_map<int, int> hash;
        hash[0] = 1;
        int sum = 0;
        int cnt = 0;
        for (auto& e : nums) {
            sum += e;
            int target = (sum % k + k) % k;
            if (hash.count(target)) cnt += hash[target];
            hash[target]++;
        }
        return cnt;
    }
};

class Solution05 {
public:
    int findMaxLength(vector<int>& nums) {
        for (auto& e : nums)
            if (e == 0)
                e = -1;
        int len = nums.size();
        // 需要计算出最长数组的长度
        vector<int> dp(nums.size() + 1);
        dp[0] = 0;
        for (int i = 1; i <= nums.size(); i++)
            dp[i] = dp[i - 1] + nums[i - 1];
        // 找到两个相同字段和的下标

        // // 找到第一个为0的下标和最后一个下标
        // int left = 0, right = 0;
        // // if (nums[0] == 0) left = 0;
        // // else {

        // // }
        // for (int i = 1; i <= len; i++)
        //     if (dp[i] == 0) {
        //         left = i;
        //         break;
        //     }
        // for (int i = len; i >= 1; i--) {
        //     if (dp[i] == 0) {
        //         right = i;
        //         break;
        //     }
        // }
        // return right - left + 1;
        // 计算出的是有多少个子数组
        // 在 map 后面不存个数，存下坐标

        int ret = 0;
        int sum = 0;
        unordered_map<int, int> hash;
        hash[0] = -1;
        // for (auto e : nums) {
        //     sum += e;
        //     if (hash.count(sum)) cnt += hash[sum];
        //     hash[sum]++;
        // }

        for (int i = 0; i < len; i++) {
            sum += nums[i];
            if (hash.count(sum) == 0) hash[sum] = i;
            else {
                ret = max(ret, i - hash[sum]);
            }
        }
        return ret;
    }
};

int main() {
    int n, m, q;
    cin >> n >> m >> q;
    vector<vector<long long>> v(n + 1, vector<long long>(m + 1)), dp(n + 1, vector<long long>(m + 1));
    for (int i = 0; i < n; i++)
        dp[i][0] = 0;
    for (int j = 0; j < m; j++)
        dp[0][j] = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            cin >> v[i][j];
            dp[i][j] = v[i][j] + dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1];
        }
    for (int i = 0; i < q; i++) {
        int left1, right1, left2, right2;
        cin >> left1 >> right1 >> left2 >> right2;
        cout << dp[left2][right2] - dp[left2][right1 - 1] - dp[left1 - 1][right2] + dp[left1 - 1][right1 - 1] << endl;
    }
    return 0;
}
